﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DOTNET101_Objects_Classes_Structs
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public class Person
    {
        // Field
        public string name;

        // Constructor
        public Person()
        {
            name = "unknown";
        }

        // Method
        public void SetName(string newName)
        {
            name = newName;
        }
    }
    
    public class TestPerson
    {
        static void Test()
        {
            Person person1 = new Person();
            System.Console.WriteLine(person1.name);

            person1.SetName("John Smith");
            System.Console.WriteLine(person1.name);
        }
    }

    public struct CoOrds
    {
        public int x, y;

        public CoOrds(int p1, int p2)
        {
            x = p1;
            y = p2;
        }
    }

    // Declare a struct object without "new."
    public class TestCoOrdsNoNew
    {
        public static void Test()
        {
            // Declare an object:
            CoOrds coords1;

            // Initialize:
            coords1.x = 10;
            coords1.y = 20;

            // Display results:
            System.Console.Write("CoOrds 1: ");
            System.Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);
        }
    }

    // compile with: /target:library
    public class D
    {
        public virtual void DoWork(int i)
        {
            // Original implementation.
        }
    }

    public abstract class E : D
    {
        public abstract override void DoWork(int i);
    }

    public class F : E
    {
        public override void DoWork(int i)
        {
            // New implementation.
        }
    }

    // compile with: csc /target:library abstractshape.cs
    public abstract class Shape
    {
        private string m_id;

        public Shape(string s)
        {
            // calling the set accessor of the Id property.
            Id = s;
        }

        public string Id
        {
            get
            {
                return m_id;
            }

            set
            {
                m_id = value;
            }
        }

        // Area is a read-only property - only a get accessor is needed:
        public abstract double Area
        {
            get;
        }

        public override string ToString()
        {
            return Id + " Area = " + string.Format("{0:F2}", Area);
        }
    }

    // compile with: csc /target:library /reference:abstractshape.dll shapes.cs
    public class Square : Shape
    {
        private int m_side;

        public Square(int side, string id)
            : base(id)
        {
            m_side = side;
        }

        public override double Area
        {
            get
            {
                // Given the side, return the area of a square:
                return m_side * m_side;
            }
        }
    }

    public class Circle : Shape
    {
        private int m_radius;

        public Circle(int radius, string id)
            : base(id)
        {
            m_radius = radius;
        }

        public override double Area
        {
            get
            {
                // Given the radius, return the area of a circle:
                return m_radius * m_radius * System.Math.PI;
            }
        }
    }

    public class Rectangle : Shape
    {
        private int m_width;
        private int m_height;

        public Rectangle(int width, int height, string id)
            : base(id)
        {
            m_width = width;
            m_height = height;
        }

        public override double Area
        {
            get
            {
                // Given the width and height, return the area of a rectangle:
                return m_width * m_height;
            }
        }
    }

    // compile with: csc /reference:abstractshape.dll;shapes.dll shapetest.cs
    public class TestClassShape
    {
        public static void Test()
        {
            Shape[] shapes =
        {
            new Square(5, "Square #1"),
            new Circle(3, "Circle #1"),
            new Rectangle( 4, 5, "Rectangle #1")
        };

            System.Console.WriteLine("Shapes Collection");
            foreach (Shape s in shapes)
            {
                System.Console.WriteLine(s);
            }
        }
    }

    public class BaseClass
    {
        public void DoWork() { }
        public int WorkField;
        public int WorkProperty
        {
            get { return 0; }
        }
    }

    public class DerivedClass : BaseClass
    {
        public new void DoWork() { }
        public new int WorkField;
        public new int WorkProperty
        {
            get { return 0; }
        }
    }

    public class TestDerivedClass
    {
        public static void Test()
        {
            DerivedClass B = new DerivedClass();
            B.DoWork();  // Calls the new method.

            BaseClass A = (BaseClass)B;
            A.DoWork();  // Calls the old method.
        }
    }

    public class BaseClass1
    {
        public virtual void DoWork() { }
        public virtual int WorkProperty
        {
            get { return 0; }
        }
    }
    public class DerivedClass1 : BaseClass1
    {
        public override void DoWork() { }
        public override int WorkProperty
        {
            get { return 0; }
        }
    }

    public class TestDerivedClass1
    {
        public static void Test()
        {
            DerivedClass1 B = new DerivedClass1();
            B.DoWork();  // Calls the new method.

            BaseClass1 A = (BaseClass1)B;
            A.DoWork();  // Calls the old method.
        }
    }

    // Define the base class
    class Car
    {
        public virtual void DescribeCar()
        {
            System.Console.WriteLine("Four wheels and an engine.");
        }
    }

    // Define the derived classes
    class ConvertibleCar : Car
    {
        public new virtual void DescribeCar()
        {
            base.DescribeCar();
            System.Console.WriteLine("A roof that opens up.");
        }
    }

    class Minivan : Car
    {
        public override void DescribeCar()
        {
            base.DescribeCar();
            System.Console.WriteLine("Carries seven people.");
        }
    }

    public class TestCar
    {
        public static void TestCars1()
        {
            Car car1 = new Car();
            car1.DescribeCar();
            System.Console.WriteLine("----------");

            ConvertibleCar car2 = new ConvertibleCar();
            car2.DescribeCar();
            System.Console.WriteLine("----------");

            Minivan car3 = new Minivan();
            car3.DescribeCar();
            System.Console.WriteLine("----------");
        }

//Four wheels and an engine. 

//---------- 

//Four wheels and an engine. 

//A roof that opens up. 

//---------- 

//Four wheels and an engine. 

//Carries seven people. 

//---------- 
        
        public static void TestCars2()
        {
            Car[] cars = new Car[3];
            cars[0] = new Car();
            cars[1] = new ConvertibleCar();
            cars[2] = new Minivan();

            foreach (Car vehicle in cars)
            {
                System.Console.WriteLine("Car object: " + vehicle.GetType());
                vehicle.DescribeCar();
                System.Console.WriteLine("----------");
            }
        }

//Car object: YourApplication.Car 

//Four wheels and an engine. 

//---------- 

//Car object: YourApplication.ConvertibleCar 

//Four wheels and an engine. 

//---------- 

//Car object: YourApplication.Minivan 

//Four wheels and an engine. 

//Carries seven people. 

//---------- 
    }

    class Person2
    { 
      string name;
      int age;

      Person2(string name, int age)
      {
        this.name = name;
        this.age = age;
      }

      public override string ToString() 
      {
         string s = age.ToString();
         return "Person: " + name + " " + s;
      }
    }

    interface IControl
    {
        void Paint();
    }
    interface ISurface
    {
        void Paint();
    }
    class SampleClass : IControl, ISurface
    {
        // Both ISurface.Paint and IControl.Paint call this method.
        public void Paint()
        {
        }

        void IControl.Paint()
        {
            System.Console.WriteLine("IControl.Paint");
        }
        void ISurface.Paint()
        {
            System.Console.WriteLine("ISurface.Paint");
        }

    }

    public class TestSampleClass
    {
        public void Test()
        {
            SampleClass obj = new SampleClass();
            //obj.Paint();  // Compiler error.

            IControl c = (IControl)obj;
            c.Paint();  // Calls IControl.Paint on SampleClass.

            ISurface s = (ISurface)obj;
            s.Paint(); // Calls ISurface.Paint on SampleClass.
        }
    }

    interface ILeft
    {
        int P { get; }
    }
    interface IRight
    {
        int P();
    }

    class Middle : ILeft, IRight
    {
        public int P() { return 0; }
        int ILeft.P { get { return 0; } }
    }

    interface IDimensions
    {
        float getLength();
        float getWidth();
    }

    public class Box : IDimensions
    {
        float lengthInches;
        float widthInches;

        Box(float length, float width)
        {
            lengthInches = length;
            widthInches = width;
        }
        // Explicit interface member implementation: 
        float IDimensions.getLength()
        {
            return lengthInches;
        }
        // Explicit interface member implementation:
        float IDimensions.getWidth()
        {
            return widthInches;
        }

        public static void Test()
        {
            // Declare a class instance box1:
            Box box1 = new Box(30.0f, 20.0f);

            // Declare an interface instance dimensions:
            IDimensions dimensions = (IDimensions)box1;

            // The following commented lines would produce compilation 
            // errors because they try to access an explicitly implemented
            // interface member from a class instance:                   
            //System.Console.WriteLine("Length: {0}", box1.getlength());
            //System.Console.WriteLine("Width: {0}", box1.getwidth());

            // Print out the dimensions of the box by calling the methods 
            // from an instance of the interface:
            System.Console.WriteLine("Length: {0}", dimensions.getLength());
            System.Console.WriteLine("Width: {0}", dimensions.getWidth());
        }
    }

    // Declare the English units interface:
    interface IEnglishDimensions
    {
        float Length();
        float Width();
    }

    // Declare the metric units interface:
    interface IMetricDimensions
    {
        float Length();
        float Width();
    }

    // Declare the Box class that implements the two interfaces:
    // IEnglishDimensions and IMetricDimensions:
    public class Box1 : IEnglishDimensions, IMetricDimensions
    {
        float lengthInches;
        float widthInches;

        public Box1(float length, float width)
        {
            lengthInches = length;
            widthInches = width;
        }

        // Explicitly implement the members of IEnglishDimensions:
        float IEnglishDimensions.Length()
        {
            return lengthInches;
        }

        float IEnglishDimensions.Width()
        {
            return widthInches;
        }

        // Explicitly implement the members of IMetricDimensions:
        float IMetricDimensions.Length()
        {
            return lengthInches * 2.54f;
        }

        float IMetricDimensions.Width()
        {
            return widthInches * 2.54f;
        }

        static void Test()
        {
            // Declare a class instance box1:
            Box1 box1 = new Box1(30.0f, 20.0f);

            // Declare an instance of the English units interface:
            IEnglishDimensions eDimensions = (IEnglishDimensions)box1;

            // Declare an instance of the metric units interface:
            IMetricDimensions mDimensions = (IMetricDimensions)box1;

            // Print dimensions in English units:
            System.Console.WriteLine("Length(in): {0}", eDimensions.Length());
            System.Console.WriteLine("Width (in): {0}", eDimensions.Width());

            // Print dimensions in metric units:
            System.Console.WriteLine("Length(cm): {0}", mDimensions.Length());
            System.Console.WriteLine("Width (cm): {0}", mDimensions.Width());
        }

        public class SampleRefType
        {
            public int value;
        }

        public static void TestRefType()
        {
            SampleRefType rt = new SampleRefType();
            rt.value = 44;
            ModifyObject(rt);
            System.Console.WriteLine(rt.value);
        }

        static void ModifyObject(SampleRefType obj)
        {
            obj.value = 33;
        }
    }

    public class PassingValByVal
    {
        static void SquareIt(int x)
        // The parameter x is passed by value.
        // Changes to x will not affect the original value of x.
        {
            x *= x;
            System.Console.WriteLine("The value inside the method: {0}", x);
        }
        public static void Test()
        {
            int n = 5;
            System.Console.WriteLine("The value before calling the method: {0}", n);

            SquareIt(n);  // Passing the variable by value.
            System.Console.WriteLine("The value after calling the method: {0}", n);
        }
    }

    public class PassingRefByVal
    {
        static void Change(int[] pArray)
        {
            pArray[0] = 888;  // This change affects the original element.
            pArray = new int[5] { -3, -1, -2, -3, -4 };   // This change is local.
            System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
        }

        public static void Test()
        {
            int[] arr = { 1, 4, 5 };
            System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);

            Change(arr);
            System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);
        }
    }

    public class Taxi
    {
        public bool isInitialized;
        public Taxi()
        {
            isInitialized = true;
        }
    }

    public class TestTaxi
    {
        public static void Test()
        {
            Taxi t = new Taxi();
            System.Console.WriteLine(t.isInitialized);

            // The following code, however, causes Compiler Error CS0165 because it does not use new, and because it tries to use an object that has not been initialized:
            // int i;
            // Console.WriteLine(i);
        }
    }

    // You can prevent a class from being instantiated by making the constructor private, as follows:
    class NLog
    {
        // Private Constructor:
        private NLog() { }

        public static double e = System.Math.E;  //2.71828...
    }

    class CoOrds1
    {
        public int x, y;

        // Default constructor:
        public CoOrds1()
        {
            x = 0;
            y = 0;
        }

        // A constructor with two arguments:
        public CoOrds1(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        // Override the ToString method:
        public override string ToString()
        {
            return (System.String.Format("({0},{1})", x, y));
        }
    }

    public class TestCoOrds1
    {
        public static void Test()
        {
            CoOrds1 p1 = new CoOrds1();
            CoOrds1 p2 = new CoOrds1(5, 3);

            // Display the results using the overriden ToString method:
            System.Console.WriteLine("CoOrds #1 at {0}", p1);
            System.Console.WriteLine("CoOrds #2 at {0}", p2);
        }
    }

    public class Counter
    {
        private Counter() { }
        public static int currentCount;
        public static int IncrementCount()
        {
            return ++currentCount;
        }
    }

    public class TestCounter
    {
        public static void Test()
        {
            // If you uncomment the following statement, it will generate
            // an error because the constructor is inaccessible:
            // Counter aCounter = new Counter();   // Error

            Counter.currentCount = 100;
            Counter.IncrementCount();
            System.Console.WriteLine("New count: {0}", Counter.currentCount);
        }
    }

    public class Bus
    {
        // Static constructor:
        static Bus()
        {
            System.Console.WriteLine("The static constructor invoked.");
        }

        public static void Drive()
        {
            System.Console.WriteLine("The Drive method invoked.");
        }
    }

    public class TestBus
    {
        public static void Test()
        {
            Bus.Drive();
        }
    }

    class PersonCopy
    {
        private string name;
        private int age;

        // Copy constructor.
        public PersonCopy(PersonCopy previousPerson)
        {
            name = previousPerson.name;
            age = previousPerson.age;
        }

        // Instance constructor.
        public PersonCopy(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        // Get accessor.
        public string Details
        {
            get
            {
                return name + " is " + age.ToString();
            }
        }
    }

    public class TestPersonCopy
    {
        public static void Test()
        {
            // Create a new person object.
            PersonCopy person1 = new PersonCopy("George", 40);

            // Create another new object, copying person1.
            PersonCopy person2 = new PersonCopy(person1);
            System.Console.WriteLine(person2.Details);
        }
    }

    class First
    {
        ~First()
        {
            System.Console.WriteLine("First's destructor is called");
        }
    }

    class Second : First
    {
        ~Second()
        {
            System.Console.WriteLine("Second's destructor is called");
        }
    }

    class Third : Second
    {
        ~Third()
        {
            System.Console.WriteLine("Third's destructor is called");
        }
    }

    class TestDestructors
    {
        public static void Test()
        {
            Third t = new Third();
        }
    }

    public class StudentName
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int ID;
    }

    public class TestStudentName
    {
        public static void Test()
        {
            StudentName student = new StudentName
            {
                FirstName = "Craig",
                LastName = "Playstead",
                ID = 116
            };

            List<StudentName> students = new List<StudentName>()
            {
              new StudentName {FirstName="Craig", LastName="Playstead", ID=116},
              new StudentName {FirstName="Shu", LastName="Ito", ID=112, },
              new StudentName {FirstName="Stefan", LastName="Rißling", ID=113, },
              new StudentName {FirstName="Rajesh", LastName="Rotti", ID=114, }
            };

            var studentInfos =
                from p in students
                select new { p.FirstName, p.LastName };

            foreach (var st in students)
            {
                StudentName s = (StudentName)st;
                Console.WriteLine(s.FirstName);
                Console.WriteLine(s.LastName);
            }

            Dictionary<int, StudentName> studentsdict = new Dictionary<int, StudentName>()
            {
                { 111, new StudentName {FirstName="Sachin", LastName="Karnik", ID=211}},
                { 112, new StudentName {FirstName="Dina", LastName="Salimzianova", ID=317, }},
                { 113, new StudentName {FirstName="Andy", LastName="Ruth", ID=198, }}
            };

        }
    }

    static class Constants
    {
        public const double Pi = 3.14;
    }

    class TestConstants
    {
        public static void Test()
        {
            double radius = 5.3;
            double area = Constants.Pi * (radius * radius);
        }
    }

    public class Container
    {
        public class Nested
        {
            private Container m_parent;

            public Nested()
            {
            }
            public Nested(Container parent)
            {
                m_parent = parent;
            }
        }
    }

    // public class:
    public class Tricycle
    {
        // protected method:
        protected void Pedal() { }

        // private field:
        private int m_wheels = 3;

        // protected internal property:
        protected internal int Wheels
        {
            get { return m_wheels; }
        }
    }

    public partial class Employee
    {
        public void DoWork()
        {
        }
    }

    public partial class Employee
    {
        public void GoToLunch()
        {
        }
    }

    [System.SerializableAttribute]
    partial class Moon { }

    [System.ObsoleteAttribute]
    partial class Moon { }


    public partial class CoOrds2
    {
        private int x;
        private int y;

        public CoOrds2(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }

    public partial class CoOrds2
    {
        public void PrintCoOrds()
        {
            System.Console.WriteLine("CoOrds: {0},{1}", x, y);
        }

    }

    class TestCoOrds2
    {
        static void Test()
        {
            CoOrds2 myCoOrds = new CoOrds2(10, 15);
            myCoOrds.PrintCoOrds();
        }
    }

    public static class TemperatureConverter
    {
        public static double CelsiusToFahrenheit(string temperatureCelsius)
        {
            // Convert argument to double for calculations.
            double celsius = System.Double.Parse(temperatureCelsius);

            // Convert Celsius to Fahrenheit.
            double fahrenheit = (celsius * 9 / 5) + 32;

            return fahrenheit;
        }

        public static double FahrenheitToCelsius(string temperatureFahrenheit)
        {
            // Convert argument to double for calculations.
            double fahrenheit = System.Double.Parse(temperatureFahrenheit);

            // Convert Fahrenheit to Celsius.
            double celsius = (fahrenheit - 32) * 5 / 9;

            return celsius;
        }
    }

    public class TestTemperatureConverter
    {
        public static void Test()
        {
            System.Console.WriteLine("Please select the convertor direction");
            System.Console.WriteLine("1. From Celsius to Fahrenheit.");
            System.Console.WriteLine("2. From Fahrenheit to Celsius.");
            System.Console.Write(":");

            string selection = System.Console.ReadLine();
            double F, C = 0;

            switch (selection)
            {
                case "1":
                    System.Console.Write("Please enter the Celsius temperature: ");
                    F = TemperatureConverter.CelsiusToFahrenheit(System.Console.ReadLine());
                    System.Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                    break;

                case "2":
                    System.Console.Write("Please enter the Fahrenheit temperature: ");
                    C = TemperatureConverter.FahrenheitToCelsius(System.Console.ReadLine());
                    System.Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                    break;

                default:
                    System.Console.WriteLine("Please select a convertor.");
                    break;
            }
        }
    }

    class TheClass
    {
        public string willIChange;
    }

    struct TheStruct
    {
        public string willIChange;
    }

    public class TestClassAndStruct
    {
        class student
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int ID { get; set; }
            public int ExamScores { get; set; }
        }

        class product
        {
            public string Color { get; set; }
            public int Price { get; set; }
        }

        static void ClassTaker(TheClass c)
        {
            c.willIChange = "Changed";
        }

        static void StructTaker(TheStruct s)
        {
            s.willIChange = "Changed";
        }

        public static void Test()
        {
            TheClass testClass = new TheClass();
            TheStruct testStruct = new TheStruct();

            testClass.willIChange = "Not Changed";
            testStruct.willIChange = "Not Changed";

            ClassTaker(testClass);
            StructTaker(testStruct);

            System.Console.WriteLine("Class field = {0}", testClass.willIChange);
            System.Console.WriteLine("Struct field = {0}", testStruct.willIChange);
            
            // Class field = Changed
            // Struct field = Not Changed     

            List<product> products = new List<product>
            {
                new product { Color="Black", Price=20 },
                new product { Color="Red", Price=40}
            };

            var productQuery =
                from prod in products
                select new { prod.Color, prod.Price };

            foreach (var v in productQuery)
            {
                Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
            }
        }

        private static void QueryByScore()
        {
            // Create the query. var is required because
            // the query produces a sequence of anonymous types.
            List<student> students = new List<student>
            {
                new student {FirstName="Test1", LastName="Test2", ID=1, ExamScores=100},
                new student {FirstName="Test3", LastName="Test4", ID=2, ExamScores=200}
            };

            var queryHighScores =
                from student in students
                where student.ExamScores > 95
                select new { student.FirstName, student.LastName };

            // Execute the query.
            foreach (var obj in queryHighScores)
            {
                // The anonymous type's properties were not named. Therefore 
                // they have the same names as the Student properties.
                Console.WriteLine(obj.FirstName + ", " + obj.LastName);
            }
        }
    }

    namespace Extensions
    {
        using System;
        using ExtensionMethodsDemo1;

        // Define extension methods for any type that implements IMyInterface.
        public static class Extension
        {
            public static void MethodA(this IMyInterface myInterface, int i)
            {
                Console.WriteLine("Extension.MethodA(this IMyInterface myInterface, int i)");
            }

            public static void MethodA(this IMyInterface myInterface, string s)
            {
                Console.WriteLine("Extension.MethodA(this IMyInterface myInterface, string s)");
            }

            // This method is never called, because the three classes implement MethodB.
            public static void MethodB(this IMyInterface myInterface)
            {
                Console.WriteLine("Extension.MethodB(this IMyInterface myInterface)");
            }
        }
    }
    namespace ExtensionMethodsDemo1
    {
        using System;
        using Extensions;

        public interface IMyInterface
        {
            void MethodB();
        }

        class A : IMyInterface
        {
            public void MethodB() { Console.WriteLine("A.MethodB()"); }
        }

        class B : IMyInterface
        {
            public void MethodB() { Console.WriteLine("B.MethodB()"); }
            public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
        }

        class C : IMyInterface
        {
            public void MethodB() { Console.WriteLine("C.MethodB()"); }
            public void MethodA(object obj) { Console.WriteLine("C.MethodA(object obj)"); }
        }

        class ExtMethodDemo
        {
            public static void Test(string[] args)
            {
                A a = new A();
                B b = new B();
                C c = new C();
                TestMethodBinding(a, b, c);
            }

            static void TestMethodBinding(A a, B b, C c)
            {
                // A has no methods, so each call resolves to 
                // the extension methods whose signatures match.
                a.MethodA(1);           // Extension.MethodA(object, int)
                a.MethodA("hello");     // Extension.MethodA(object, string)
                a.MethodB();            // A.MethodB()

                // B itself has a method with this signature.
                b.MethodA(1);           // B.MethodA(int)
                b.MethodB();            // B.MethodB()

                // B has no matching method, but Extension does.
                b.MethodA("hello");     // Extension.MethodA(object, string)

                // In each case C has a matching instance method.
                c.MethodA(1);           // C.MethodA(object)
                c.MethodA("hello");     // C.MethodA(object)
                c.MethodB();            // C.MethodB()
            }
        }
    }
    /* Output:
        Extension.MethodA(this IMyInterface myInterface, int i)
        Extension.MethodA(this IMyInterface myInterface, string s)
        A.MethodB()
        B.MethodA(int i)
        B.MethodB()
        Extension.MethodA(this IMyInterface myInterface, string s)
        C.MethodA(object obj)
        C.MethodA(object obj)
        C.MethodB()
     */

    class ImplicitlyTypedLocals2
    {
        public static void Test()
        {
            string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };

            // If a query produces a sequence of anonymous types, 
            // then you must also use var in the foreach statement.
            var upperLowerWords =
                 from w in words
                 select new { Upper = w.ToUpper(), Lower = w.ToLower() };

            // Execute the query
            foreach (var ul in upperLowerWords)
            {
                Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
            }
        }
    }
    /* Outputs:
        Uppercase: APPLE, Lowercase: apple
        Uppercase: BLUEBERRY, Lowercase: blueberry
        Uppercase: CHERRY, Lowercase: cherry        
     */
}
